1、创建套接字
	domain: 协议族类型
		AF_INET IPV4套接字
		AF_INET6 IPV6套接字
		AF_UNIX, AF_LOCAL 本地套接字
	type: 套接字类型
		SOCK_STREAM 流套接字，用于TCP
		SOCK_DGRAM 数据报套接字，用于UDP
	protocol: 协议类型
		0 不指定协议
		IPPROTO_TCP TCP传输协议
		IPPROTO_UDP UDP传输协议
		IPPROTO_STCP STCP传输协议
		IPPROTO_TIPC TIPC传输协议
	成功返回套接字，失败返回-1
	int socket(int domain, int type, int protocol);
2、绑定本地IP和端口
	sockfd: 套接字描述符
	addr: IP地址，代表要绑定的地址
	addrlen: addr的长度
	成功返回0，失败返回-1
	int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
3、开启监听
	sockfd: 套接字描述符
	backlog: 一次能够等待的最大连接数目
	成功返回0，失败返回-1
	int listen(int sockfd, int backlog);
4、获取一个新连接
	sockfd: 套接字描述符
	addr: 返回客户端地址
	addrlen: addr的长度
	成功返回套接字，失败返回-1
	int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
5、连接服务器
	TCP调用后会建立真正的连接，UDP调用后不会建立正在的连接，仅仅是对套接字进行了设置，以方便时若read和write
	sockfd: 套接字描述符
	addr: 服务器地址
	addrlen: addr的长度
	成功返回0，失败返回-1
	int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
6、发送数据
	对于TCP套接字，如果对一个对端关闭的套接字执行写操作会产生管道破裂信号
	sockfd: 套接字描述符
	buf: 待发送的数据
	len: 数据长度
	flags: 发送标志，一般为0
		MSG_DONTROUTE 旁路底层协议的路由机制
		MSG_DONTWAIT 将单个I/O操作设置为非阻塞模式
		MSG_OOB 发送带外数据
	dest_addr: 目标地址
	addrlen: dest_addr的长度
	成功返回发送的字节数，失败返回-1
	ssize_t write(int sockfd, const void *buf, size_t len);
	ssize_t send(int sockfd, const void *buf, size_t len, int flags);
	ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
7、接收数据
	对于TCP连接，如果对端关闭连接函数会返回0
	sockfd: 套接字描述符
	buf: 返回读取的数据
	len: buf的长度
	flags: 读取标志，一般为0
		MSG_DONTWAIT 将单个I/O操作设置为非阻塞模式
		MSG_OOB 读取带外数据
		MSG_PEEK 可以查看可读的信息，在接收数据后不会将这些数据丢失
		MSG_WAITALL 直到读到请求的数据字节数时才返回。
	src_addr: 源地址
	addrlen: src_addr长度
	成功返回读取的字节数，失败返回-1
	ssize_t read(int sockfd, void *buf, size_t len);
	ssize_t recv(int sockfd, void *buf, size_t len, int flags);
	ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
8、关闭套接字
	sockfd: 套接字描述符
	how: 关闭方式
		0 停止接收当前数据，并拒绝以后的数据接收
		1 停止发送数据，并丢弃未发送的数据
		2 停止接收和发送数据
	成功返回0，失败返回-1
	int close(int sockfd);
	int shutdown(int sockfd, int how);
9、设置套接字属性
	sockfd: 套接字描述符
	level: 要设置的协议栈层次
		SOL_SOCKET 套接字层
		IPPROTO_TCP TCP层
		IPPROTO_IP IPV4层
		IPPROTO_IPV6 IPV6层
	optname: 设置的选项
		选项			数据类型			含义
		SO_ACCEPTCONN	BOOL				获取套接字是否能被监听（仅getsockopt）
		SO_BROADCAST	BOOL				允许套接口传送广播信息
		SO_BINDTODEV	char *				将套接字绑定到指定网卡
		SO_DEBUG		BOOL				启用网络驱动调试
		SO_DONTROUTE	BOOL				旁路底层协议的路由机制
		SO_DONTLINER	BOOL				不要因为数据未发送就阻塞关闭操作
		SO_ERROR		int					获取错误状态并清除（仅getsockopt）
		SO_KEEPALIVE	BOOL				发送“keep-alive”包
		SO_LINGER		struct linger*		如关闭时有未发送数据，则等待
		TCP_NODELAY		BOOL				禁止发送的Nagle算法，禁用后会提高网络实时性，但是利用率会降低
		SO_OOBINLINE	BOOL				将带外数据放到普通数据中
		SO_RCVBUF		int					设置接收缓冲区大小
		SO_RCVLOWAT		int					接收水线，当接收缓冲区数据超过此数量时通知进程可读
		SO_RCVTIMEO		int					接收超时
		SO_REUSEADDR	BOOL				允许套接字端口和一个已在使用中的地址绑定（参见bind()）
		SO_SNDBUF		int					指定发送缓冲区大小
		SO_SNDLOWAT		int					发送水线，当发送缓冲区数据少于此数量时通知进程可写
		SO_SNDTIMEO		int					发送超时
		SO_TYPE			int					获取套接口类型（仅getsockopt）
	optval: 指向设置的参数，其数据类型根据optname决定
	optlen: optval参数的长度
	成功返回0，失败返回-1
	int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
10、获取套接字属性
	sockfd: 套接字描述符
	level: 要获取的协议栈层次
	optname: 要获取的选项
	optval: 返回选项值
	optlen: optval参数的长度
	成功返回0，失败返回-1
	int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
11、获取远端地址信息
	sockfd: 套接字描述符
	addr: 返回对端地址
	addrlen: addr的长度
	成功返回0，失败返回-1
	int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
12、获取本地地址信息
	sockfd: 套接字描述符
	addr: 返回本地地址
	addrlen: addr的长度
	成功返回0，失败返回-1
	int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
13、select多路服用
	nfds: 被监听的文件描述符的总数，它比所有文件描述符集合中最大的文件描述符的大1
	readfds: 可读事件描述符集合，NULL表示忽略
	writefds: 可写事件描述符集合，NULL表示忽略
	exceptfds: 异常等事件描述符集合，NULL表示忽略，在网络编程中select能处理的异常情况只有一种: socket上接收到带外数据
	timeout: 超时时间，相对值，NULL表示一直等待
	超时返回0;失败返回-1;成功返回大于0的整数，表示就绪描述符的数目
	int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
	复位描述符集合
	int FD_ZERO(int fd, fd_set *fdset);
	将描述符从描述符集合中清除
	int FD_CLR(int fd, fd_set *fdset);
	将描述符加入到描述符集合中
	int FD_SET(int fd, fd_set *fd_set);
	测试描述符集合中是否存在某个描述符
	int FD_ISSET(int fd, fd_set *fdset);
14、poll多路服用
	fds: 描述符及事件组成的集合
		 struct pollfd {
			int   fd;         /* 描述符，<0则忽略*/
			short events;     /* 要监测的事件
								POLLIN		有数据可读
								POLLRDNORM	有普通数据可读
								POLLRDBAND	有优先数据可读
								POLLPRI		有紧迫数据可读
								POLLOUT		写数据不会导致阻塞
								POLLWRNORM	写普通数据不会导致阻塞
								POLLWRBAND	写优先数据不会导致阻塞
								POLLERR		指定的文件描述符发生错误
								POLLHUP		指定的文件描述符挂起事件
								POLLNVAL	指定的文件描述符非法 */
			short revents;    /* 实际发生的事件 */
		};
	nfds: fds的个数
	timeout: 超时时间，ms，0立即返回，负数一直阻塞
	超时返回0;失败返回-1;成功返回大于0的整数，表示就绪描述符的数目
	int poll(struct pollfd *fds, nfds_t nfds, int timeout);
15、IP地址转换
	将字符串IP地址转换为网络序列IP地址
	cp: 字符串IP地址
	inp: 网络字节序IP地址
	成功返回0，失败返回-1
	int inet_aton(const char *cp, struct in_addr *inp);
	将字符串IP地址转换为网络序列IP地址
	cp: 字符串IP地址，不能是"255.255.255.255"
	成功返回IP地址，失败返回-1
	in_addr_t inet_addr(const char *cp);
	将字符串IP地址转换为主机序列IP地址
	cp: 字符串IP地址，不能是"255.255.255.255"
	成功返回IP地址，失败返回-1
	in_addr_t inet_network(const char *cp);
	将网络序列IP地址转换为字符串IP地址
	in: 网络字节序IP地址
	返回字符串IP地址
	char *inet_ntoa(struct in_addr in);
	将网络字节序IP地址转换为主机字节序IP地址
	in: 网络字节序IP地址
	返回主机字节序IP地址
	in_addr_t inet_lnaof(struct in_addr in);
	将主机字节序IP转网络字节序IP
	in: 主机字节序IP
	返回网络字节序IP
	in_addr_t inet_netof(struct in_addr in);
16、字节序转换
	主机字节序转网络字节序
	hostlong: 32位主机字节序数据
	hostshort: 16位主机字节序数据
	返回网络字节序数据
	uint32_t htonl(uint32_t hostlong);
    uint16_t htons(uint16_t hostshort);
	网络字节序转主机字节序
	hostlong: 32位网络字节序数据
	hostshort: 16位网络字节序数据
	返回主机字节序数据
    uint32_t ntohl(uint32_t netlong);
    uint16_t ntohs(uint16_t netshort);
17、IP地址数据结构
	通用数据结构：
		struct sockaddr{
			u_short sa_family;	//协议簇；AF_INET ：IPv4协议簇
			char sa_data[14]; 	//14字节协议地址
		};
	internet环境下套接字的数据结构：
		struct in_addr{
			in_addr_t s_addr;
		};
		struct sockaddr_in{
			u_short sin_family;     	//协议簇；AF_INET ：IPv4协议簇
			u_short sin_port;       	//端口，网络字节序
			struct in_addr sin_addr;	//IP地址，网络字节序
			char sin_zero[8];       	//8字节填充，保持为0
		};